package com.ifcar.app.util;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import android.content.Context;
import android.content.Entity;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;


/**
 * This helper class download images from the Internet and binds those with the provided ImageView.
 *
 * <p>It requires the INTERNET permission, which should be added to your application's manifest
 * file.</p>
 *
 * A local cache of downloaded images is maintained internally to improve performance.
 */
public class BaseImageDownloader {
    public enum Mode { NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT }
    private Mode mode = Mode.CORRECT;
    private Context mContext = null;
    private Bitmap mDefaultBm = null;
    private String flag;
    private Thread mThread;
    private  SharedPreferences set_prefs;
    
    public BaseImageDownloader (Context context, Bitmap defaultBm) {
       mContext = context;
       mDefaultBm = defaultBm;
       set_prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
    }
   
    public BaseImageDownloader (Context context, Bitmap defaultBm, int width, int height, String c) {
        mContext = context;
        mDefaultBm = defaultBm;
        bitmapW = width;
        bitmapH = height;
        cut = c;
        set_prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
     }
    
    /**
     * 设定图片下载线程
     * @param thread
     */
    public void setThread(Thread thread) {
    	mThread = thread;
    }
    
    /**
     * 设定默认图片
     * @param bitmap
     */
    public void setDefaultBitmap(Bitmap bitmap) {
        mDefaultBm = bitmap;
    }
    
    /**
     * 通过url获取图片 优先获取本地图片
     * @param imgUrl
     * @return Bitmap对象
     */
    public Bitmap getBitmap(String imgUrl){
    	
    	Bitmap bitmap = null;
    	StringBuilder img = new StringBuilder();
    	img.append(imgUrl);
    	String localimgfile = img.substring(img.lastIndexOf("/")+1, img.length());
    	if(PicUtil.isLocalPicExit(localimgfile)) {
    		bitmap = PicUtil.readTempJPEGFile(localimgfile);
    	}else{
    		bitmap = forceDownload(imgUrl);
    	}
    	return bitmap;
    	
    }
    
    /**
     * 下载非本地而且是网络图片，用在离线下载
     * @param imgUrl
     */
    public long getImageforBatche(String imgUrl){
    	StringBuilder img = new StringBuilder();
    	img.append(imgUrl);
    	if(!PicUtil.isLocalPicExit(img.substring(img.lastIndexOf("/")+1, img.length()))) {
    		return downloadImageforBatche(imgUrl);
    	}else{
    	    return 0;
    	}
    }
    /**
     * 根据url为imageview对象下载图片，利用三级缓存机制：内存、本地文件、网络
     * @param url
     * @param imageView
     */
    public void download(String url, ImageView imageView) {
        if (TextUtils.isEmpty(url)) {
            imageView.setImageBitmap(mDefaultBm);
            return;
        }
        resetPurgeTimer();
    	Bitmap bitmap = null;
    	if (mRoundR > 0) {
            bitmap = getBitmapFromCache("RoundR_" + mRoundR + "_" + url);
    	} else {
    	    bitmap = getBitmapFromCache(url);
    	}

    	WeakReference<Bitmap> bitmapReference = null;	
    	if(bitmap == null &&
    			PicUtil.isLocalPicExit(url.substring(url.lastIndexOf("/")+1, url.length()))) {

            if(bitmapW != 0 && bitmapH != 0) { 
            	bitmapReference = new WeakReference<Bitmap>(PicUtil.resizeBitmap(mContext, 
                		PicUtil.readTempJPEGFile(url.substring(url.lastIndexOf("/")+1, url.length())), 
                		bitmapW, bitmapH));
            } else bitmapReference = new WeakReference<Bitmap>(PicUtil.readTempJPEGFile(url.substring(url.lastIndexOf("/")+1, url.length())));
            bitmap = bitmapReference.get();
            
    	}
    	
        if (bitmap == null) {
            boolean downpic = set_prefs.getBoolean("downpic", false);
            if(Tools.isshowimg(downpic, mContext)){
                forceDownload(url, imageView);
            }else{
                if(null!=mDefaultBm){
                    imageView.setImageBitmap(mDefaultBm);
                }
            }
            
        } else {
            cancelPotentialDownload(url, imageView);
            if (mRoundR > 0) {
                bitmap = PicUtil.getRoundedCornerBitmap(bitmap, mRoundR);
            }
            imageView.setImageBitmap(bitmap);
        }
    }
    
    /**
     * Download the specified image from the Internet and binds it to the provided ImageView. The
     * binding is immediate if the image is found in the cache and will be done asynchronously
     * otherwise. A null bitmap will be associated to the ImageView if an error occurs.
     *
     * @param url The URL of the image to download.
     * @param imageView The ImageView to bind the downloaded image to.
     * @param w The Picture width.
     * @param h The picture height.
     */
    public void downloadPictures(String imgUrl, ImageView imageView, int w, int h, String c, Bitmap map, String f) {
    	bitmapW = w;
    	bitmapH = h;
    	cut = c;
    	flag = f;
    	mDefaultBm = map;
    	
    	if(imgUrl == null || imgUrl.equals("")) {
    		imageView.setImageBitmap(map);
    	} else {
    	   	WeakReference<Bitmap> bitmapReference = null;	
        	
        	Bitmap bitmap = null;
        	
        	resetPurgeTimer();
        	
        	if(!imgUrl.startsWith("http://")){
        	    imgUrl = "http://"+imgUrl;
        	}
        	
        	imgUrl = PicUtil.get3G_PhotoResize(imgUrl, w, h);
        	
        	Logger.i("img.tostring()", imgUrl);
        	bitmap = getBitmapFromCache(imgUrl);
        	
        	if(bitmap == null && PicUtil.isLocalPicExit(imgUrl.substring(imgUrl.lastIndexOf("/")+1, imgUrl.length()))) {
        		bitmapReference = new WeakReference<Bitmap>(PicUtil.readTempJPEGFile(imgUrl.substring(imgUrl.lastIndexOf("/")+1, imgUrl.length())));	
        		bitmap = bitmapReference.get();
        	}
        	
            if (bitmap == null) {
                boolean downpic = set_prefs.getBoolean("downpic", false);
                if(Tools.isshowimg(downpic, mContext)){
                    forceDownload(imgUrl.toString(), imageView);
                }
            } else {
                cancelPotentialDownload(imgUrl.toString(), imageView);
                imageView.setImageBitmap(bitmap);
            }
    	}
    	
 
    }
    
    /**
     * 异步下载投票图片
     * @param imgUrl 图片URL
     * @param imageView 绑定的ImageView组件
     */
    public void downloadVoteImage(String url, ImageView imageView) {
    	resetPurgeTimer();
     	Bitmap bitmap = null;
     	bitmap = getBitmapFromCache(url);
     	WeakReference<Bitmap> bitmapReference = null;	
     	
     	if(bitmap == null && PicUtil.isLocalPicExit(url.substring(url.lastIndexOf("/")+1, url.length()))) {
             
            if(bitmapW != 0 && bitmapH != 0) { 
            	bitmapReference = new WeakReference<Bitmap>(PicUtil.cutBitmap(PicUtil.readTempJPEGFile(url.substring(url.lastIndexOf("/")+1, url.length())), 
                 		bitmapW, bitmapH));
            } else {
                bitmapReference = new WeakReference<Bitmap>(PicUtil.readTempJPEGFile(url.substring(url.lastIndexOf("/")+1, url.length())));
            }
            
            bitmap = bitmapReference.get();
             
     	}
     	
         if (bitmap == null) {
             forceDownload(url, imageView);
         } else {
             cancelPotentialDownload(url, imageView);
             imageView.setImageBitmap(bitmap);
         }
    }
    

    /**
     * Same as download but the image is always downloaded and the cache is not used.
     * Kept private at the moment as its interest is not clear.
     */
    private void forceDownload(String url, ImageView imageView) {

        if (url == null) {
            
            if(null!=mDefaultBm){
                imageView.setImageBitmap(mDefaultBm);
            }
            return;
        }

        if (cancelPotentialDownload(url, imageView)) {
        	
            try {
               switch (mode) {
                   case NO_ASYNC_TASK:
                       Bitmap bitmap = downloadBitmap(url);
                       addBitmapToCache(url, bitmap);
                       imageView.setImageBitmap(bitmap);
                       break;

                   case NO_DOWNLOADED_DRAWABLE:
                       BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
                       task.execute(url);
                       break;

                   case CORRECT:
                       task = new BitmapDownloaderTask(imageView);
                       DownloadedDrawable downloadedDrawable = new DownloadedDrawable(mContext.getResources(), task, mDefaultBm);  
                       if(null!=downloadedDrawable){
                    	   imageView.setImageDrawable(downloadedDrawable);
                       }
                       task.execute(url);
                       break;
               }
            } catch (Exception e) {
               e.printStackTrace();
            }
        }
    }
    
    /**
     * 强制下载图片
     * @param url
     * @return
     */
    private Bitmap forceDownload(String url) {
        
        if (url == null) { 
            return null;
        }

        try {
            Bitmap bitmap = downloadBitmap(url);
            return bitmap;
         } catch (Exception e) {
             return null;
         }
        
    }

    /**
     * Returns true if the current download has been canceled or if there was no download in
     * progress on this image view.
     * Returns false if the download in progress deals with the same url. The download is not
     * stopped in that case.
     */
    private static boolean cancelPotentialDownload(String url, ImageView imageView) {
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     * @param imageView Any imageView
     * @return Retrieve the currently active download task (if any) associated with this imageView.
     * null if there is no such task.
     */
    private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
        if (imageView != null) {
            Drawable drawable = imageView.getDrawable();
            if (drawable instanceof DownloadedDrawable) {
                DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
                return downloadedDrawable.getBitmapDownloaderTask();
            }
        }
        return null;
    }
    /**
     * 离线下载批量下载图片
     * @param url
     */
    private long downloadImageforBatche(String url){
    	
		Bitmap bm;
		long size = 0;
		try {
			if (url == null || url.equals("")) {
				return 0;
			}
			HttpParams httpParams = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, Constant.TIMEOUT);
            HttpConnectionParams.setSoTimeout(httpParams, Constant.TIMEOUT);
            DefaultHttpClient httpClient = NeteaseHttpClient.getHttpClient(httpParams);
			Tools.setHttpClientHostProxy(httpClient, mContext);
			HttpGet request = new HttpGet(PicUtil.getImgUrlByNetType(url,mContext));
			HttpResponse response = httpClient.execute(request);
			HttpEntity entity = response.getEntity();
			InputStream is = entity.getContent();
			size = entity.getContentLength();
			if (is == null)
				return 0;
			else {
				bm = BitmapFactory.decodeStream(new FlushedInputStream(is));
				
				if(null!=bm){
					if (bitmapW != 0 && bitmapH != 0 && cut == null){
					    bm = PicUtil.resizeBitmap(mContext, bm, bitmapW, bitmapH);
					}

					if ("Y".equals(cut)){
					    bm = PicUtil.cutBitmap(bm, bitmapW, bitmapH);
					}

					PicUtil.saveMyBitmap(url.substring(url.lastIndexOf("/") + 1, url.length()), bm);
					bm.recycle();
					bm = null;
				}
				
				
			}
			is.close();
			
		} catch (OutOfMemoryError e) {
           
        }catch (Exception e) {
				
		}
		return size<0?0:size;
    }
    
    /**
     * 通过URL下载图片
     * @param url
     * @return Bitmap
     */
	Bitmap downloadBitmap(String url) {
		Bitmap bm;
		try {
			if (url == null || url.equals("")) {
				return mDefaultBm;
			}
			HttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams, Constant.TIMEOUT);
            HttpConnectionParams.setSoTimeout(httpParams, Constant.TIMEOUT);
			DefaultHttpClient httpClient = NeteaseHttpClient.getHttpClient(httpParams);
			Tools.setHttpClientHostProxy(httpClient, mContext);
			HttpGet request = new HttpGet(PicUtil.getImgUrlByNetType(url,mContext));
			HttpResponse response = httpClient.execute(request);
			HttpEntity  entity = response.getEntity();
			InputStream is = entity.getContent();
			
			if (is == null){
			    return mDefaultBm;
			}else {
				bm = BitmapFactory.decodeStream(new FlushedInputStream(is));
				if (bitmapW != 0 && bitmapH != 0 && cut == null){
				    bm = PicUtil.resizeBitmap(mContext, bm, bitmapW, bitmapH);
				}
				
				if ("Y".equals(cut)){
				    bm = PicUtil.cutBitmap(bm, bitmapW, bitmapH);
				}

				if(null!=bm){
					PicUtil.saveMyBitmap(url.substring(url.lastIndexOf("/") + 1, url.length()), bm);
				}
			}
			
			is.close();
			entity.consumeContent();
			return bm;
		}catch (OutOfMemoryError e) {
		    return mDefaultBm;
		} catch (Exception e) {
			return mDefaultBm;
		}
	}

	/**
	 * 通过url 和 httpget请求下载图片，httpget可以被控制
	 * @param url
	 * @param request
	 * @return
	 */
	Bitmap downloadBitmap(String url,HttpGet request) {
        Bitmap bm;
        try {
            if (url == null || url.equals("")) {
                return mDefaultBm;
            }
            HttpParams httpParams = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, Constant.TIMEOUT);
            HttpConnectionParams.setSoTimeout(httpParams, Constant.TIMEOUT);
            DefaultHttpClient httpClient = NeteaseHttpClient.getHttpClient(httpParams);
            Tools.setHttpClientHostProxy(httpClient, mContext);
            HttpResponse response = httpClient.execute(request);
            HttpEntity  entity = response.getEntity();
            InputStream is = entity.getContent();
            
            if (is == null)
                return mDefaultBm;
            else {
                bm = BitmapFactory.decodeStream(new FlushedInputStream(is));
                if (bitmapW != 0 && bitmapH != 0 && cut == null){
                    bm = PicUtil.resizeBitmap(mContext, bm, bitmapW, bitmapH);
                }
               
                if ("Y".equals(cut)){
                    bm = PicUtil.cutBitmap(bm, bitmapW, bitmapH);
                }

                if(null!=bm){
                    PicUtil.saveMyBitmap(url.substring(url.lastIndexOf("/") + 1, url.length()), bm);
                }
                
                if (mRoundR > 0) {
                    bm = PicUtil.getRoundedCornerBitmap(bm, mRoundR);
                }
                
            }
            
            is.close();
            entity.consumeContent();
            return bm;
        }catch (OutOfMemoryError e) {
            return mDefaultBm;
        } catch (Exception e) {
            return mDefaultBm;
        }
    }

    /*
     * An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
     */
    public static class FlushedInputStream extends FilterInputStream {
        public FlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }

        @Override
        public long skip(long n) throws IOException {
            long totalBytesSkipped = 0L;
            while (totalBytesSkipped < n) {
                long bytesSkipped = in.skip(n - totalBytesSkipped);
                if (bytesSkipped == 0L) {
                    int b = read();
                    if (b < 0) {
                        break;  // we reached EOF
                    } else {
                        bytesSkipped = 1; // we read one byte
                    }
                }
                totalBytesSkipped += bytesSkipped;
            }
            return totalBytesSkipped;
        }
    }

    /**
     * The actual AsyncTask that will asynchronously download the image.
     */
    class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
        

        private String url;
        private final WeakReference<ImageView> imageViewReference;
        private HttpGet httpGet = null;
        public BitmapDownloaderTask(ImageView imageView) {
           imageViewReference = new WeakReference<ImageView>(imageView);
        }
        @Override
        protected void onCancelled() {
            // TODO Auto-generated method stub
            super.onCancelled();
            synchronized(this){
                if(null!=httpGet){
                    httpGet.abort();
                    httpGet = null;
                }
            }
        }
        /**
         * Actual download method.
         */
        @Override
        protected Bitmap doInBackground(String... params) {
            try {
                url = params[0];
                synchronized(this){
                    if(isCancelled()){
                        return mDefaultBm;
                    }
                    httpGet = new HttpGet(PicUtil.getImgUrlByNetType(url,mContext));
                }
                return downloadBitmap(url,httpGet);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return mDefaultBm;
            }
        }

        /**
         * Once the image is downloaded, associates it to the imageView
         */
        @Override
        protected void onPostExecute(Bitmap bitmap) {
           
            if(null!=bitmap){
                if (mRoundR > 0) {
                    addBitmapToCache("RoundR_" + mRoundR + "_" + url, bitmap);
                } else {
                    addBitmapToCache(url, bitmap);
                }
            }
            
            if (isCancelled()) {
                bitmap = mDefaultBm;
            }else{
                if (imageViewReference != null) {
                    ImageView imageView = imageViewReference.get();
                    if(imageView != null) {
                       BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
                       if (bitmapDownloaderTask != null && this == bitmapDownloaderTask
                               && mThread != null && mThread == Thread.currentThread()) {
                           try {
                               if(null!=bitmap){
                                   imageView.setImageBitmap(bitmap);
                               }else{
                                   if(null!=mDefaultBm){
                                       imageView.setImageBitmap(mDefaultBm);
                                   }
                                   
                               }
                               
                           } catch (Exception e) {
                               e.printStackTrace();
                           }
                       }
                    }
                } 
            }
         
        }
    }


    /**
     * A fake Drawable that will be attached to the imageView while the download is in progress.
     *
     * <p>Contains a reference to the actual download task, so that a download task can be stopped
     * if a new binding is required, and makes sure that only the last started download process can
     * bind its result, independently of the download finish order.</p>
     */
    static class DownloadedDrawable extends BitmapDrawable {
        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

        public DownloadedDrawable(Resources resources, BitmapDownloaderTask bitmapDownloaderTask, Bitmap bm) {
            super(resources, bm);
            bitmapDownloaderTaskReference =
                new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference.get();
        }
    }

    public void setMode(Mode mode) {
        this.mode = mode;
        clearCache();
    }

   
    /*
     * Cache-related fields and methods.
     *
     * We use a hard and a soft cache. A soft reference cache is too aggressively cleared by the
     * Garbage Collector.
     */
   
    private static final int HARD_CACHE_CAPACITY = 60;
    private static final int DELAY_BEFORE_PURGE = 60 * 1000; // in milliseconds

    // Hard cache, with a fixed maximum capacity and a life duration
    private final HashMap<String, Bitmap> sHardBitmapCache =
        new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {
        @Override
        protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
            if (size() > HARD_CACHE_CAPACITY) {
                // Entries push-out of hard reference cache are transferred to soft reference cache
                sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
                return true;
            } else
                return false;
        }
    };

    // Soft cache for bitmaps kicked out of hard cache
    private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =
        new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);

    private final Handler purgeHandler = new Handler();

    private final Runnable purger = new Runnable() {
        public void run() {
            clearCache();
        }
    };

    /**
     * Adds this bitmap to the cache.
     * @param bitmap The newly downloaded bitmap.
     */
    private void addBitmapToCache(String url, Bitmap bitmap) {
        if (bitmap != null) {
            synchronized (sHardBitmapCache) {
                sHardBitmapCache.put(url, bitmap);
            }
        }
    }

    /**
     * @param url The URL of the image that will be retrieved from the cache.
     * @return The cached bitmap or null if it was not found.
     */
    private Bitmap getBitmapFromCache(String url) {
        // First try the hard reference cache
        try{
            synchronized (sHardBitmapCache) {
                final Bitmap bitmap = sHardBitmapCache.get(url);
                if (bitmap != null) {
                    // Bitmap found in hard cache
                    // Move element to first position, so that it is removed last
                    sHardBitmapCache.remove(url);
                    sHardBitmapCache.put(url, bitmap);
                    return bitmap;
                }
            }

            // Then try the soft reference cache
            SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url);
            if (bitmapReference != null) {
                final Bitmap bitmap = bitmapReference.get();
                if (bitmap != null) {
                    // Bitmap found in soft cache
                    return bitmap;
                } else {
                    // Soft reference has been Garbage Collected
                    sSoftBitmapCache.remove(url);
                }
            }
        }catch(Exception ex){
            
        }
        return null;
    }
 
    /**
     * Clears the image cache used internally to improve performance. Note that for memory
     * efficiency reasons, the cache will automatically be cleared after a certain inactivity delay.
     */
    public void clearCache() {
        sHardBitmapCache.clear();
        sSoftBitmapCache.clear();
    }

    /**
     * Allow a new delay before the automatic cache clear is done.
     */
    private void resetPurgeTimer() {
        purgeHandler.removeCallbacks(purger);
        purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);
    }
    
    private int bitmapW = 0;
    private int bitmapH = 0;
    private String cut;
    public void setBitmapWandH(int w, int h, String c) {
    	bitmapW = w;
    	bitmapH = h;
    	cut = c;
    }
    
    private float mRoundR;
    
    public void setRoundR(float r) {
        mRoundR = r;
    }
}

